package juc.scenarios.startup;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * CountDownLatch 演示程序
 * 
 * 模拟多服务启动检查场景
 */
public class CountDownLatchDemo {
    
    public static void main(String[] args) throws InterruptedException {
        System.out.println("=== CountDownLatch 演示：多服务启动检查 ===");
        
        // 要检查的服务数量
        int serviceCount = 4;
        
        // 创建CountDownLatch，计数器为服务数量
        CountDownLatch latch = new CountDownLatch(serviceCount);
        
        // 创建线程池
        ExecutorService executor = Executors.newFixedThreadPool(serviceCount);
        
        System.out.println("开始检查 " + serviceCount + " 个服务...");
        long startTime = System.currentTimeMillis();
        
        // 提交服务检查任务
        String[] services = {"数据库服务", "缓存服务", "消息队列服务", "配置中心服务"};
        
        for (int i = 0; i < serviceCount; i++) {
            final String serviceName = services[i];
            final int serviceIndex = i;
            
            executor.submit(() -> {
                try {
                    // 模拟服务检查耗时（1-3秒）
                    long checkDuration = (long) (Math.random() * 2000 + 1000);
                    System.out.println("开始检查 " + serviceName + "，预计耗时 " + checkDuration + "ms");
                    
                    Thread.sleep(checkDuration);
                    
                    // 模拟90%的健康概率
                    boolean isHealthy = Math.random() < 0.9;
                    
                    if (isHealthy) {
                        System.out.println("✅ " + serviceName + " 检查通过 (耗时: " + checkDuration + "ms)");
                    } else {
                        System.out.println("❌ " + serviceName + " 检查失败 (耗时: " + checkDuration + "ms)");
                    }
                    
                } catch (InterruptedException e) {
                    System.out.println("❌ " + serviceName + " 检查被中断");
                    Thread.currentThread().interrupt();
                } finally {
                    // 无论成功失败，都要减少计数器
                    latch.countDown();
                    System.out.println("🔔 " + serviceName + " 完成检查，剩余未完成任务: " + latch.getCount());
                }
            });
        }
        
        // 等待所有服务检查完成（最多等待10秒）
        boolean completed = latch.await(10, TimeUnit.SECONDS);
        
        long endTime = System.currentTimeMillis();
        long totalDuration = endTime - startTime;
        
        if (completed) {
            System.out.println("\n🎉 所有服务检查完成！");
            System.out.println("总耗时: " + totalDuration + "ms");
            System.out.println("平均每个服务检查时间: " + (totalDuration / serviceCount) + "ms");
            
            // 如果串行检查，总时间会是所有服务检查时间的总和
            // 并行检查的总时间 ≈ 最慢的服务检查时间
            System.out.println("通过并行检查，节省了大约 " + (totalDuration * (serviceCount - 1) / 2) + "ms");
            
        } else {
            System.out.println("\n⏰ 检查超时！");
            System.out.println("当前已完成任务数: " + (serviceCount - latch.getCount()));
        }
        
        // 关闭线程池
        executor.shutdown();
        executor.awaitTermination(5, TimeUnit.SECONDS);
        
        System.out.println("\n=== 演示完成 ===");
        
        // CountDownLatch的特点总结
        System.out.println("\n📚 CountDownLatch 特点总结：");
        System.out.println("1. 一个线程等待多个线程完成任务");
        System.out.println("2. 计数器只能递减，不能重置");
        System.out.println("3. 支持超时等待");
        System.out.println("4. 适用于一次性事件");
        System.out.println("5. 无法重复使用");
    }
}